﻿var net=require("net");
var ws=require("ws");
var log=require("../utils/log");
var tcppkg=require("./tcppkg");
var protocol=require("./protocol");
var service_manager=require("./service_manager");

var netbus={
    tcp_server:tcp_server,
    ws_server:ws_server,
    
    get_client_session:get_client_session,
    get_app_server_session:get_app_server_session,

    set_client_session:set_client_session,
    remove_client_session:remove_client_session,

    connect_tcp_app_server:connect_tcp_app_server,
    connect_ws_app_server:connect_ws_app_server,

    session_close:on_session_close,
};

//存储所有的客户端socket
var client_session_list={};
var client_session_id=100000; //以极大值作为用户的登陆id,然后会被改成数据库中的用户id

function get_client_session(session_id) {
	return client_session_list[session_id];
}

function set_client_session(session_id,session){

	client_session_list[session_id]=session;
}

function remove_client_session(session_id){
	client_session_list[session_id]=null;
	delete client_session_list[session_id];
}


//客户端接入
function on_session_enter(session,is_ws,is_encrypt){

	//session就是服务器与客户端建立通讯配对的socket
	if (is_ws){
		log.info("客户端接入:",session._socket.remoteAddress+":"+session._socket.remotePort);
	}
	else{
		log.info("客户端接入:",session.remoteAddress+":"+session.remotePort);
	}

	//每一个客户端都带上一个数据包缓冲区
	session.last_pkg=null;
	session.is_ws=is_ws;
	session.is_encrypt=is_encrypt; //是否socket是加密通道
	session.is_connected=true;

	session.send_cmd=on_session_send_cmd;
	session.send_data=service_manager.on_send;
	session.broadcast_data=service_manager.on_broadcast;
	
	client_session_id++;
	client_session_list[client_session_id]=session;
	session.session_id=client_session_id;
}

//客户端断开
function on_session_exit(session){
	
	if (session.is_ws){
		log.info("客户端断开:",session._socket.remoteAddress+":"+session._socket.remotePort);
	}
	else{
		log.info("客户端断开:",session.remoteAddress+":"+session.remotePort);
	}

	session.is_connected=false;
	//断开玩家在所有服务模块中的数据
	service_manager.on_disconnect(session);

	//清除session
	session.last_pkg=null;
	if (client_session_list[session.session_id]){
		client_session_list[session.session_id]=null;
		delete client_session_list[session.session_id];
		session.session_id=null;
	}

}

//客户端接收
//cmd是二进制:[0001,0002,数据]
//cmd是json:[0:1,1:2,2:数据]
function on_session_recv_cmd(session,cmd){

	//假如socket是加密通道,需要将数据解密
	if (session.is_encrypt){
		cmd=protocol.decrypt(cmd);
	}

	//发送给其中的服务器管理模块
	service_manager.on_recv_client_cmd(session,cmd);
}

//客户端发送
//cmd是二进制:[0001,0002,数据]
//cmd是json:[0:1,1:2,2:数据]
function on_session_send_cmd(cmd){
	if (!this.is_connected)
		return;

	//假如socket是加密通道,需要将数据加密
	if (this.is_encrypt){
		cmd=protocol.encrypt(cmd);
	}

	if (this.is_ws){
		this.send(cmd);
	}
	else
	{
		var data=tcppkg.package_data(cmd);
		this.write(data);
	}
}

//主动关闭客户端
function on_session_close(session){
	if (session.is_ws)
		session.close();
	else
		session.end();
}

//////////////////////////////////////////////////////////
function tcp_session_event(session,is_encrypt){

	on_session_enter(session,false,is_encrypt);

	//客户端关闭
	session.on("close",()=>{
		on_session_exit(session);
	});

	session.on("error",(err)=>{
		log.error(err);
	});

	//接收客户端发送过来的数据
	session.on("data",(data)=>{
		//数据包已经处理完
		if (session.last_pkg==null)
		{
			session.last_pkg =data;
		}
		//还有剩余的数据没处理完
		else
		{
			//连接新传过来的数据
			session.last_pkg=Buffer.concat([session.last_pkg,data]);
		}

		var pkgdata=tcppkg.unpackage_data(session.last_pkg);

		session.last_pkg=pkgdata.remain;

		pkgdata.data.forEach(function(cmd){
			//cmd是二进制流
		    on_session_recv_cmd(session,cmd);
		});
	});
}


function tcp_server(ip,port,is_encrypt){
	log.info("TCP服务器启动:",ip,port);
	var server=net.createServer((client_socket)=>{
		tcp_session_event(client_socket,is_encrypt);
	});

	server.on("close",()=>{
		log.error("关闭服务器");
	});

	server.on("error",(err)=>{
		log.error(err);
	});

	server.listen({
		host:ip,
		port:port,
		exclusive:true
	});
}
///////////////////////////////////////////////////////////////
function ws_session_event(session,is_encrypt){

	on_session_enter(session,true,is_encrypt);
	//客户端关闭
	session.on("close",()=>{
		on_session_exit(session);
	});

	session.on("error",(err)=>{
		log.error(err);
	});

	//接收客户端发送过来的数据
	session.on("message",(cmd)=>{
	    on_session_recv_cmd(session,cmd);
	});
}

function ws_server(ip,port,is_encrypt){
	log.info("WS服务器启动:",ip,port);
	var server=new ws.Server({
		host:ip,
		port:port
	});

	server.on("connection",(client_socket)=>{
		ws_session_event(client_socket,is_encrypt);
	});

	server.on("close",()=>{
		log.error("关闭服务器");
	});

	server.on("error",(err)=>{
		log.error(err);
	});
}


//////////////////////////////////////////////////////////
//连接app_server
var app_server_session_list={};
function get_app_server_session(stype) {
	return app_server_session_list[stype];
}

function on_app_server_connected(session,stype,is_ws,is_encrypt){
	//session就是网关与app_server建立通讯配对的socket
	if (is_ws){
		log.info("连接到app_server:",stype,session._socket.remoteAddress+":"+session._socket.remotePort);
	}
	else{
		log.info("连接到app_server:",stype,session.remoteAddress+":"+session.remotePort);
	}


	session.last_pkg=null;
	session.is_ws=is_ws;
	session.is_encrypt=is_encrypt; //是否socket是加密通道
	session.is_connected=true;

	session.send_cmd=on_session_send_cmd;
	session.send_data=service_manager.on_send;
	
	app_server_session_list[stype]=session;
	session.session_id=stype;
}

function on_app_server_disconnect(session){
	//与app_server端断开连接
	if (session.is_ws){
		log.info("与app_server断开:",session.session_id,session._socket.remoteAddress+":"+session._socket.remotePort);
	}
	else{
		log.info("与app_server断开:",session.session_id,session.remoteAddress+":"+session.remotePort);
	}

	session.is_connected=false;
	session.last_pkg=null;
	if (app_server_session_list[session.session_id]){
		app_server_session_list[session.session_id]=null;
		delete app_server_session_list[session.session_id];
		session.session_id=null;
	}
}

function on_app_server_recv_cmd(session,cmd){
	//假如socket是加密通道,需要将数据解密
	if (session.is_encrypt){
		cmd=protocol.decrypt(cmd);
	}

	//发送给其中的服务器管理模块
	service_manager.on_recv_app_server_cmd(session,cmd);
}

function connect_tcp_app_server(stype,host,port,is_encrypt){
	var session=net.connect({
		host:host,
		port:port
	});

	session.is_connected=false;
	session.on("connect",function() {
		on_app_server_connected(session,stype,false, is_encrypt);
	});

	session.on("close", function() {
		if (session.is_connected == true) {
			on_app_server_disconnect(session);	
		}
		session.end();

		// 重新连接到服务器
		setTimeout(function() {
			log.warn("重新连接app_server: ", stype, host, port);
			connect_tcp_app_server(stype, host, port, is_encrypt);
		}, 3000);
		// end 
	});

	session.on("error", function(err) {
		
	});

	//接收AppServer端发送过来的数据
	session.on("data",function(data){
		//数据包已经处理完
		if (session.last_pkg==null)
		{
			session.last_pkg =data;
		}
		//还有剩余的数据没处理完
		else
		{
			//连接新传过来的数据
			session.last_pkg=Buffer.concat([session.last_pkg,data]);
		}

		var pkgdata=tcppkg.unpackage_data(session.last_pkg);

		session.last_pkg=pkgdata.remain;

		pkgdata.data.forEach(function(cmd){
			//cmd是二进制流
		    on_app_server_recv_cmd(session,cmd);
		});
	});
}

function connect_ws_app_server(stype,host,port,is_encrypt){
	var session=new ws("ws://"+host+":"+port);
	session.is_connected=false;
	session.on("open",function(){
		on_app_server_connected(session,stype,true, is_encrypt);
	});

	session.on("close", function() {
		if (session.is_connected == true) {
			on_app_server_disconnect(session);	
		}
		session.close();

		// 重新连接到服务器
		setTimeout(function() {
			log.warn("重新连接app_server: ", stype, host, port);
			connect_ws_app_server(stype, host, port, is_encrypt);
		}, 3000);
		// end 
	});

	session.on("error", function(err) {
		
	});

	session.on("message",function(cmd){
	    on_app_server_recv_cmd(session,cmd);
	});
}


module.exports=netbus;